数据存储¶
7.1 存储机制¶
本系统存储采用文件+LevelDb构成,文件用来存放区块以及链信息,LevelDB存放索引信息以及WorldState信息。
7.1.1 系统创建及初始化¶
- 多实例存储机制,主要支持交易的与执行
- 单实例存储机制,主要支持数据的持久化与API接口
7.1.2 存储内容¶
- LevelDB存储索引
- File System存储区块
7.1.3 Merkle计算¶
- Merkle计算的原则采用增量方式,目的是减少内存和CPU的占用。
- Merkle计算方法是:首先计算当前块的Worldstate的Hash256,然后连接上一个块计算的Merkle值,再次计算Hash256,即为当前的Merkle值。
7.1.4 存储功能¶
- 单实例的LevelDB操作需要支持事务机制,包含提交与回滚
- 支持区块的读写
- 支持WorldState的读写
- 支持Merkle的计算
- 支持外部检索
- 支持读写集的校验
7.2 存储结构¶
7.3 存储类¶
7.3.1 LevelDB¶
接口类,描述公共对外访问的全局方法,包括以下方法:
从系统获取某个键对应的值:
def Get(key : String):Array[Byte]存储某个键的值到系统:
def Put (key : String,bb : Array[Byte]):Boolean从系统中删除某个键的值,目前没有实现,因为RepChain不允许删除:
def Delete (key : String) : Boolean把某个字节的值转为字符串:
def toString(b : Array[Byte]):String把某个字节的值转为长整型:
def toLong(b : Array[Byte]):Long把某个字节的值转为整型:
def toInt(b : Array[Byte]):Int打印某个map的数据:
def printlnHashMap(map : mutable.HashMap[String,Array[Byte]])获取当前的系统名称:
def getSystemName:String获取当前实例的名称:
def getInstanceName:String获取当前增量的Merkle的字节值:
def GetComputeMerkle:Array[Byte]获取当前增量的Merkle的字符串值:
def GetComputeMerkle4String:String
7.3.2 AbstractLevelDB¶
该类实现公共方法,实现的方法有:toString,toLong,toInt,PrintlnHashMap,GetComputeMerkle,getComputMerkle4String。
该类新增以下两个方法,这两个方法属于保护类型,外部不需要调用:
- protected def ReloadMerkle 初始化时装载上一个块的Merkle值
- protected def PutWorldStateToMerkle(key:String,value:Array[Byte]) 系统WorldState改变时自动修改Merle值
7.3.3 IDataAccess¶
该类实现LevelDB数据库的操作,并且添加外部操作定义。
数据库操作方法有:
实现系统名称的获取:
override def getSystemName:String实现当前实例的获取:
override def getInstanceName:String实现是否开启事务:
def IsBeginTrans : Boolean实现开启事务:
def BeginTrans私有方法,保存Merkle值,内部自动调用:
private def SaveMerkle实现事务提交:
def CommitTrans实现事务回滚:
def RollbackTrans实现指定键值的获取:
override def Get(key : String):Array[Byte]实现存储指定键值的存储到数据库:
override def Put (key : String,bb : Array[Byte]):Boolean暂时不实现:
override def Delete (key : String) : Boolean实现键值的模糊查询(指定模糊匹配方法,前端一致,后端一致,包含):
def FindByLike(searchkey : String,searchmode : Int):mutable.HashMap[String,Array[Byte]]实现键的模糊查询:
def FindKeyByLike(searchkey : String,searchmode : Int):Array[String]实现前端一致模糊匹配查询:
def FindByLike(searchkey : String):mutable.HashMap[String,Array[Byte]]
- 外部操作方法定义:
通过block Hash值获取Block:
def getBlockByBase64Hash(base64:String):Array[Byte]根据block的hash值获取block:
def getBlockByHash(bh:String):Array[Byte]根据交易id获取这个交易隶属的block:
def getBlockByTxId(bh:String):Array[Byte]根据链的高度来获取等于这个高度值的block:
def getBlockByHeight(h:Long):Array[Byte]从某个高度开始(包含这个高度)的所有块取出来,h:开始的高度,h 必须大于0,高度是从1开始
limits 返回块的数量,默认值为0,如果大于0,返回指定数量的块,如果块数小于该值返回实际数量
默认最多1000条:
def getBlocksFromHeight(h:Int,limits:Int):Array[Array[Byte]]根据高度获取block:
def getBlocksFromHeight(h:Int):Array[Array[Byte]]根据高度获取多个Block:
def getBlocks4ObjectFromHeight(h:Int,limits:Int):Array[Block]根据高度获取所有Block:
def getBlocks4ObjectFromHeight(h:Int):Array[Block]根据链的高度来获取等于这个高度值的block:
def getBlock4ObjectByHeight(h:Long):Block获取区块链信息:
def getBlockChainInfo():BlockchainInfo返回成功写入的块数,写入多个区块:
def restoreBlocks(blocks:Array[Block]):Int写入单个区块:
def restoreBlock(block:Block):Boolean获取链码的高度:
def getBlockHeight():Long获取系统的所有交易数量:
def getBlockAllTxNumber():Long获取当前的区块文件编号:
def getMaxFileNo():Int
7.3.4 ImpDataAccess¶
实现IDataAccess定义的外部操作方法。
7.3.5 ImpDataPreload¶
实现LevelDB数据的快照(内存数据)操作方法,增加背书时针对读写指令集的验证以及多个实例的管理。
增加的背书验证方法:
从区块中获取指定交易对应链码id:
private def getTxidFormBlock(block:Block,txid:String):String验证指令集函数:
def VerifyForEndorsement(block:Block):Boolean多实例管理类:
MultiDBMgr存储所有的动态预执行操作实例,所有实例被存储在map结构中,该类会自动管理这些实例,如果没有被Free,MultiDBMgr会自动Free超过一分钟没有操作的实例。
7.3.6 BlockHelp¶
该类属于单实例类,负责文件系统操作,读写区块信息。
获取当前区块文件长度:
public long getFileLength(long fileno)throws Exception判断是否需要新生成一个区块文件:
public boolean isAddFile(long fileno,int blength)throws Exception指定位置读取某个区块:
public byte[] readBlock(long fileno,long startpos,int length)throws Exception指定位置写入某个区块:
public boolean writeBlock(long fileno,long startpos,byte[] bb)throws Exception
